/* Includes ------------------------------------------------------------------*/
#include "ntime.h"
#include "time.h"
#include "string.h"
/* typedef -------------------------------------------------------------------*/
/* define --------------------------------------------------------------------*/
/* macro ---------------------------------------------------------------------*/
/* variables -----------------------------------------------------------------*/
uint64_t _ticks = 0;
double _timestamp = 0;
uint32_t _tspMsLast, _tspMsCompensation = 0,  _timer = 0;
struct tm _calendar;
/* function prototypes -------------------------------------------------------*/
/* functions -----------------------------------------------------------------*/
__attribute__((weak)) void NETimestampHook_Set(double last, double now){};
__attribute__((weak)) void NETimerHook_Set(uint32_t last, uint32_t now){};
__attribute__((weak)) void NETickHook_Set(uint32_t last, uint32_t now){};
/*********************************************************************************************/

// ticks get, set and add, the count of millise second since device start

/********************************************************************************************/
uint32_t NETick_Get(void)
{   return _ticks;  }
uint32_t NETick_Set(uint32_t n)
{   
    uint32_t temp = _ticks;
    _ticks = n; 
    NETickHook_Set(temp, n);
    return _ticks;
}
uint32_t NETick_Add(int n)
{   
    _ticks += n;  
    return _ticks;
}
/*********************************************************************************************/

// timer get, set and add, the count of second since device start

/********************************************************************************************/
uint32_t NETimer_Get(void)
{   return _timer;  }
uint32_t NETimer_Set(uint32_t n)
{   
    uint32_t temp = _timer;
    _timer = n;  
    NETimerHook_Set(temp, n);
    return _timer;
}
uint32_t NETimer_Add(int n)
{   
    _timer += n;  
    return _timer;
}
/*********************************************************************************************/

// timestamp, set and add, the count of second since 1990-01-01 00:00:00

/********************************************************************************************/
uint32_t NETimestamp_GetInteger(void)
{   return (uint32_t)_timestamp;  }
double NETimestamp_GetDecimal(void)
{   return (_timestamp - (uint64_t)_timestamp);  }
double NETimestamp_Get(void)
{   
#ifdef NE_TSP_COMPENSATION
    return (_timestamp + (double)(NETick_Get() - _tspMsLast) / 1000);  
#else
    return _timestamp;
#endif
}
double NETimestamp_Set(double n)
{   
#ifdef NE_TSP_COMPENSATION
    _tspMsCompensation = (double)NETick_Get();
#endif
    double temp = _timestamp;
    _timestamp = n;
    NETimestampHook_Set(temp, n);
    
    return _timestamp;
}
double NETimestamp_Add(double n)
{   
    _timestamp += n;  
#ifdef NE_TSP_COMPENSATION
    if(_tspMsCompensation != 0)
    {   _timestamp -= (n - (double)(NETick_Get() - _tspMsCompensation) / 1000); }
    _tspMsCompensation = 0;
    _tspMsLast = NETick_Get();
#endif
    return _timestamp;
}
/*********************************************************************************************/

// calendar

/********************************************************************************************/
struct tm * NECalendar_Get()
{
    return &_calendar;
}
struct tm * NECalendar_Convert(int timeZone)
{
    time_t timestamp = NETimestamp_GetInteger() + timeZone * 3600;
    struct tm *calendarTemp = localtime(&timestamp);
    memcpy(&_calendar, calendarTemp, sizeof(struct tm));

    _calendar.tm_year += 1900;
    _calendar.tm_mon += 1;

    return &_calendar;
}
